/**
  ******************************************************************************
  * @file    sym32l010_hal_spi.h
  * @author  AE Team
  * @version 1.0.3
  * @date    2024-05-28
  * @brief   Header file of SPI HAL module.
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 SIYIMicro.
  * All rights reserved.</center></h2>
  *
  *
  ******************************************************************************
  */


/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SYM32L010_HAL_SPI_H
#define __SYM32L010_HAL_SPI_H

#ifdef __cplusplus
extern "C" {
#endif

/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include "sym32l010_hal_def.h"


/******************************************************************************/
/* Global type definitions                                                    */
/******************************************************************************/
//配置工作模式为主机或从机
typedef enum
{
    SPI_WORKMODE_MASTER        = (0x1UL << SPIx_CR1_MSTR_Pos),        // 主机模式
    SPI_WORKMODE_SLAVE         = (0x0UL << SPIx_CR1_MSTR_Pos)         // 从机模式
} SPI_WorkModeTypeDef;

/* 配置通信模式 ---------------------------------------------------------------*/
typedef enum
{
    SPI_COMM2LINES_FullDuplex  = (0x0UL << SPIx_CR1_MODE_Pos),        // 双向全双工
    SPI_COMM1LINE_TxOnly       = (0x1UL << SPIx_CR1_MODE_Pos),        // 单工只发
    SPI_COMM1LINE_RxOnly       = (0x2UL << SPIx_CR1_MODE_Pos),        // 单工只收
    SPI_COMM1LINE_HalfDuplex   = (0x3UL << SPIx_CR1_MODE_Pos)         // 单线半双工
} SPI_CommLinesTypeDef;

/* 配置数据位宽 -------------------------------------------------------------------*/
typedef enum
{
    SPI_DATAWIDTH_4BIT         = (0x3UL << SPIx_CR1_WIDTH_Pos),       // 位宽为 4BIT
    SPI_DATAWIDTH_5BIT         = (0x4UL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_6BIT         = (0x5UL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_7BIT         = (0x6UL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_8BIT         = (0x7UL << SPIx_CR1_WIDTH_Pos),       // 位宽为 8BIT
    SPI_DATAWIDTH_9BIT         = (0x8UL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_10BIT        = (0x9UL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_11BIT        = (0xAUL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_12BIT        = (0xBUL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_13BIT        = (0xCUL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_14BIT        = (0xDUL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_15BIT        = (0xEUL << SPIx_CR1_WIDTH_Pos),
    SPI_DATAWIDTH_16BIT        = (0xFUL << SPIx_CR1_WIDTH_Pos)        // 位宽为 16BIT
} SPI_DataWidthTypeDef;

/* 配置SCK极性 ----------------------------------------------------------------*/
typedef enum
{
    SPI_SCKPOLARITY_NEGATIVE   = (0x0UL << SPIx_CR1_CPOL_Pos),        // 空闲时，SCK为低电平
    SPI_SCKPOLARITY_POSITIVE   = (0x1UL << SPIx_CR1_CPOL_Pos)         // 空闲时，SCK为高电平
} SPI_SckPolarityTypeDef;

/* 配置SCK相位 ----------------------------------------------------------------*/
typedef enum
{
    SPI_SCKPHASE_1EDGE         = (0x0UL << SPIx_CR1_CPHA_Pos),        // 前边沿采样/后边沿移位
    SPI_SCKPHASE_2EDGE         = (0x1UL << SPIx_CR1_CPHA_Pos)         // 前边沿移位/后边沿采样
} SPI_SckPhaseTypeDef;

/* 配置SCK与PCLK的分频系数 ----------------------------------------------------*/
typedef enum
{
    SPI_SCKSRC_PCLKDIV2        = (0x0UL << SPIx_CR1_BR_Pos),          // SCK = PCLK/2
    SPI_SCKSRC_PCLKDIV4        = (0x1UL << SPIx_CR1_BR_Pos),          // SCK = PCLK/4
    SPI_SCKSRC_PCLKDIV8        = (0x2UL << SPIx_CR1_BR_Pos),          // SCK = PCLK/8
    SPI_SCKSRC_PCLKDIV16       = (0x3UL << SPIx_CR1_BR_Pos),          // SCK = PCLK/16
    SPI_SCKSRC_PCLKDIV32       = (0x4UL << SPIx_CR1_BR_Pos),          // SCK = PCLK/32
    SPI_SCKSRC_PCLKDIV64       = (0x5UL << SPIx_CR1_BR_Pos),          // SCK = PCLK/64
    SPI_SCKSRC_PCLKDIV128      = (0x6UL << SPIx_CR1_BR_Pos),          // SCK = PCLK/128
    SPI_SCKSRC_PCLKDIV256      = (0x7UL << SPIx_CR1_BR_Pos)           // SCK = PCLK/256
} SPI_SckSourceTypeDef;

/* 配置比特位顺序 -------------------------------------------------------------*/
typedef enum
{
    SPI_FIRSTBIT_MSB           = (0x0UL << SPIx_CR1_LSBF_Pos),        // 最高有效位收发在前
    SPI_FIRSTBIT_LSB           = (0x1UL << SPIx_CR1_LSBF_Pos)         // 最低有效位收发在前
} SPI_FirstBitTypeDef;

/* 配置NCS管脚为硬件或软件 -----------------------------------------------------*/
typedef enum
{
    SPI_NCS_HARD_OUTPUT        = (0x1UL << SPIx_CR1_SSM_Pos),         // 主机输出
    SPI_NCS_HARD_INPUT         = (0x0UL << SPIx_CR1_SSM_Pos),         // 主机输入、从机输入
    SPI_NCS_SOFT               = (0x1UL << SPIx_CR1_SSM_Pos)          // 从机软件选中
} SPI_NcsModeTypeDef;

/* 从机未被选中时MISO管脚配置 --------------------------------------------------*/
typedef enum
{
    SPI_SLAVEMISO_CMOS         = (0x0UL << SPIx_CR1_MISOHZ_Pos),      // 从机未被选中时MISO输出CMOS高
    SPI_SLAVEMISO_HIGHZ        = (0x1UL << SPIx_CR1_MISOHZ_Pos)       // 从机软件选中时MISO为高阻态
} SPI_SlaveMisoCfgTypeDef;

/* 主机模式延时采样配置 --------------------------------------------------------*/
typedef enum
{
    SPI_MASTERSMP_NORMAL       = (0x0UL << SPIx_CR1_SMP_Pos),         // 主机模式正常采样
    SPI_MASTERSMP_DELAY        = (0x1UL << SPIx_CR1_SMP_Pos)          // 主机模式延时采样，延时约20nS
} SPI_MasterSmpCfgTypeDef;

/* 数字滤波使能控制 ------------------------------------------------------------*/
typedef enum
{
    SPI_FILTER_DISABLE         = (0x0UL << SPIx_CR1_FLTEN_Pos),       // 数字滤波禁止
    SPI_FILTER_ENABLE          = (0x1UL << SPIx_CR1_FLTEN_Pos)        // 数字滤波使能
} SPI_FilterEnTypeDef;

/* 主机模式帧与帧之间间隔配置 --------------------------------------------------*/
typedef enum
{
    SPI_MASTERGAP_NONE         = (0x0UL << SPIx_CR1_GAP_Pos),         // 无间隔
    SPI_MASTERGAP_1SCK         = (0x1UL << SPIx_CR1_GAP_Pos),         // 1个SCK周期间隔
    SPI_MASTERGAP_2SCK         = (0x2UL << SPIx_CR1_GAP_Pos),         // 2个SCK周期间隔
    SPI_MASTERGAP_3SCK         = (0x3UL << SPIx_CR1_GAP_Pos),         // 3个SCK周期间隔
    SPI_MASTERGAP_4SCK         = (0x4UL << SPIx_CR1_GAP_Pos),         // 4个SCK周期间隔
    SPI_MASTERGAP_5SCK         = (0x5UL << SPIx_CR1_GAP_Pos),         // 5个SCK周期间隔
    SPI_MASTERGAP_6SCK         = (0x6UL << SPIx_CR1_GAP_Pos),         // 6个SCK周期间隔
    SPI_MASTERGAP_7SCK         = (0x7UL << SPIx_CR1_GAP_Pos),         // 7个SCK周期间隔
    SPI_MASTERGAP_8SCK         = (0x8UL << SPIx_CR1_GAP_Pos),         // 8个SCK周期间隔
    SPI_MASTERGAP_9SCK         = (0x9UL << SPIx_CR1_GAP_Pos),         // 9个SCK周期间隔
    SPI_MASTERGAP_10SCK        = (0xAUL << SPIx_CR1_GAP_Pos),         // 10个SCK周期间隔
    SPI_MASTERGAP_11SCK        = (0xBUL << SPIx_CR1_GAP_Pos),         // 11个SCK周期间隔
    SPI_MASTERGAP_12SCK        = (0xCUL << SPIx_CR1_GAP_Pos),         // 12个SCK周期间隔
    SPI_MASTERGAP_13SCK        = (0xDUL << SPIx_CR1_GAP_Pos),         // 13个SCK周期间隔
    SPI_MASTERGAP_14SCK        = (0xEUL << SPIx_CR1_GAP_Pos),         // 14个SCK周期间隔
    SPI_MASTERGAP_15SCK        = (0xFUL << SPIx_CR1_GAP_Pos),         // 15个SCK周期间隔
} SPI_MasterGapTypeDef;

/* SPI初始化结构体 -------------------------------------------------------------*/
typedef struct
{
    SPI_WorkModeTypeDef          WorkMode;                            // 工作模式
    SPI_CommLinesTypeDef         CommLines;                           // 通信模式
    SPI_DataWidthTypeDef         DataWidth;                           // 数据宽度
    SPI_SckPolarityTypeDef       SckPolarity;                         // SCK极性
    SPI_SckPhaseTypeDef          SckPhase;                            // SCK相位
    SPI_SckSourceTypeDef         SckSource;                           // 传输时钟(SCK分频系数)
    SPI_FirstBitTypeDef          FirstBit;                            // 数据帧高低位顺序
    SPI_NcsModeTypeDef           NcsMode;                             // NCS模式配置
    SPI_FilterEnTypeDef          FilterEn;                            // 数字滤波使能控制，仅当fpclk大于8倍fsck时才能使能该功能
    SPI_MasterSmpCfgTypeDef      MasterSmpCfg;                        // 主机延时采样配置
    SPI_MasterGapTypeDef         MasterGap;                           // 主机模式帧间间隔配置
    SPI_SlaveMisoCfgTypeDef      SlaveMisoCfg;                        // 从机MISO输出配置
} SPI_InitTypeDef;


typedef struct __SPI_HandleTypeDef
{
    SPI_TypeDef                  *Instance;                           // SPI 实体
    SPI_InitTypeDef              Init;                                // SPI 初始化结构体

    uint8_t                      *pTxBuffPtr;                         // SPI 待发送数据的指针
    __IO uint32_t                TxXferCount;                         // SPI 当前剩余待发送的数据帧数
    uint32_t                     TxXferSize;                          // SPI 待发送数据帧数

    uint8_t                      *pRxBuffPtr;                         // SPI 待接收数据的指针
    __IO uint32_t                RxXferCount;                         // SPI 当前剩余待接收的数据帧数
    uint32_t                     RxXferSize;                          // SPI 待接收数据帧数

    __IO HAL_StatusTypeDef       XferState;                           // SPI 传输状态 HAL_OK / HAL_ERROR / HAL_BUSY

    void (*RxISR)(struct __SPI_HandleTypeDef *hSpi);                  // SPI 接收中断函数指针
    void (*TxISR)(struct __SPI_HandleTypeDef *hSpi);                  // SPI 发送中断函数指针
} SPI_HandleTypeDef;


/******************************************************************************/
/* Global pre-processor symbols/macros ('#define')                            */
/******************************************************************************/
/* 中断触发源 -----------------------------------------------------------------*/
#define SPI_IT_SOURCE_MODF              (SPIx_IER_MODF_Msk)
#define SPI_IT_SOURCE_SSERR             (SPIx_IER_SSERR_Msk)
#define SPI_IT_SOURCE_OV                (SPIx_IER_OV_Msk)
#define SPI_IT_SOURCE_UD                (SPIx_IER_UD_Msk)
#define SPI_IT_SOURCE_SSR               (SPIx_IER_SSR_Msk)
#define SPI_IT_SOURCE_SSF               (SPIx_IER_SSF_Msk)
#define SPI_IT_SOURCE_RXNE              (SPIx_IER_RXNE_Msk)
#define SPI_IT_SOURCE_TXE               (SPIx_IER_TXE_Msk)

/* 中断触发标志 ---------------------------------------------------------------*/
#define SPI_IT_FLAG_SSLVL               (SPIx_ISR_SSLVL_Msk)
#define SPI_IT_FLAG_BUSY                (SPIx_ISR_BUSY_Msk)
#define SPI_IT_FLAG_MODF                (SPIx_ISR_MODF_Msk)
#define SPI_IT_FLAG_SSERR               (SPIx_ISR_SSERR_Msk)
#define SPI_IT_FLAG_OV                  (SPIx_ISR_OV_Msk)
#define SPI_IT_FLAG_UD                  (SPIx_ISR_UD_Msk)
#define SPI_IT_FLAG_SSR                 (SPIx_ISR_SSR_Msk)
#define SPI_IT_FLAG_SSF                 (SPIx_ISR_SSF_Msk)
#define SPI_IT_FLAG_RXNE                (SPIx_ISR_RXNE_Msk)
#define SPI_IT_FLAG_TXE                 (SPIx_ISR_TXE_Msk)


/******************************************************************************/
/* Global macro function                                                      */
/******************************************************************************/
/**
  * @brief  获取 SPI 中断触发源
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @param  ITSOURCE : 中断触发源
  *                    @arg SPI_IT_SOURCE_MODF
  *                    @arg SPI_IT_SOURCE_SSERR
  *                    @arg SPI_IT_SOURCE_OV
  *                    @arg SPI_IT_SOURCE_UD
  *                    @arg SPI_IT_SOURCE_SSR
  *                    @arg SPI_IT_SOURCE_SSF
  *                    @arg SPI_IT_SOURCE_RXNE
  *                    @arg SPI_IT_SOURCE_TXE
  * @retval None
  * @note
  */
#define HAL_SPI_GET_IT_SOURCE(HANDLE, ITSOURCE)   ((HANDLE)->Instance->IER & (ITSOURCE))

/**
  * @brief  使能 SPI 中断触发源
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @param  ITSOURCE : 中断触发源
  *                    @arg SPI_IT_SOURCE_MODF
  *                    @arg SPI_IT_SOURCE_SSERR
  *                    @arg SPI_IT_SOURCE_OV
  *                    @arg SPI_IT_SOURCE_UD
  *                    @arg SPI_IT_SOURCE_SSR
  *                    @arg SPI_IT_SOURCE_SSF
  *                    @arg SPI_IT_SOURCE_RXNE
  *                    @arg SPI_IT_SOURCE_TXE
  * @retval None
  * @note
  */
#define HAL_SPI_ENABLE_IT(HANDLE, ITSOURCE)       ((HANDLE)->Instance->IER |= (ITSOURCE))

/**
  * @brief  关闭 SPI 中断触发源
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @param  ITSOURCE : 中断触发源
  *                    @arg SPI_IT_SOURCE_MODF
  *                    @arg SPI_IT_SOURCE_SSERR
  *                    @arg SPI_IT_SOURCE_OV
  *                    @arg SPI_IT_SOURCE_UD
  *                    @arg SPI_IT_SOURCE_SSR
  *                    @arg SPI_IT_SOURCE_SSF
  *                    @arg SPI_IT_SOURCE_RXNE
  *                    @arg SPI_IT_SOURCE_TXE
  * @retval None
  * @note
  */
#define HAL_SPI_DISABLE_IT(HANDLE, ITSOURCE)      ((HANDLE)->Instance->IER &= ~((uint32_t)(ITSOURCE)))

/**
  * @brief  获取 SPI 状态标志
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @param  FLAG     : 状态标志
  *                    @arg SPI_IT_FLAG_SSLVL
  *                    @arg SPI_IT_FLAG_BUSY
  *                    @arg SPI_IT_FLAG_MODF
  *                    @arg SPI_IT_FLAG_SSERR
  *                    @arg SPI_IT_FLAG_OV
  *                    @arg SPI_IT_FLAG_UD
  *                    @arg SPI_IT_FLAG_SSR
  *                    @arg SPI_IT_FLAG_SSF
  *                    @arg SPI_IT_FLAG_RXNE
  *                    @arg SPI_IT_FLAG_TXE
  * @retval None
  * @note
  */
#define HAL_SPI_GET_FLAG(HANDLE, FLAG)            ((HANDLE)->Instance->ISR & (FLAG))

/**
  * @brief  清除 SPI 状态标志
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @param  FLAG     : 状态标志
  *                    @arg SPI_IT_FLAG_SSLVL
  *                    @arg SPI_IT_FLAG_BUSY
  *                    @arg SPI_IT_FLAG_MODF
  *                    @arg SPI_IT_FLAG_SSERR
  *                    @arg SPI_IT_FLAG_OV
  *                    @arg SPI_IT_FLAG_UD
  *                    @arg SPI_IT_FLAG_SSR
  *                    @arg SPI_IT_FLAG_SSF
  *                    @arg SPI_IT_FLAG_RXNE
  * @retval None
  * @note
  */
#define HAL_SPI_CLR_FLAG(HANDLE, FLAG)            ((HANDLE)->Instance->ICR = ~((uint32_t)(FLAG)))

/**
  * @brief  清除 SPI 除移位寄存器的其它状态标志
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @retval None
  * @note
  */
#define HAL_SPI_CLR_ALLFLAG(HANDLE)               ((HANDLE)->Instance->ICR = 0x01U)

/**
  * @brief  清除 SPI 发送缓冲区与移位寄存器
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @retval None
  * @note
  */
#define HAL_SPI_DR_FLUSH(HANDLE)                  ((HANDLE)->Instance->ICR = ~((uint32_t)SPIx_ICR_FLUSH_Msk))

/**
  * @brief  设置SSI寄存器的值用于控制NCS的电平状态
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @retval None
  * @note
  */
#define HAL_SPI_SSI_SETHIGH(HANDLE)               ((HANDLE)->Instance->SSI = 0x01U)
#define HAL_SPI_SSI_SETLOW(HANDLE)                ((HANDLE)->Instance->SSI = 0x00U)

/**
  * @brief  读取NCS管脚输入电平
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @retval 0        ：低电平
  *         非0      ：高电平
  * @note
  */
#define HAL_SPI_NCS_GETVALUE(HANDLE)              ((HANDLE)->Instance->ISR & SPIx_ISR_SSLVL_Msk)

/**
  * @brief  设置单线半双工模式数据传输方向
  * @param  hSpi     : SPI句柄指针，指向包含SPI配置、通信参数的结构体
  * @retval None
  * @note
  */
#define HAL_SPI_1LINE_HALFDUPLEX_TXMODE(HANDLE)   ((HANDLE)->Instance->CR3 = 0x01U)
#define HAL_SPI_1LINE_HALFDUPLEX_RXMODE(HANDLE)   ((HANDLE)->Instance->CR3 = 0x00U)

/******************************************************************************/
/* Exported variables ('extern', definition in C source)                      */
/******************************************************************************/


/******************************************************************************/
/* Global function prototypes ('extern', definition in C source)              */
/******************************************************************************/
HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hSpi);
HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hSpi);

HAL_StatusTypeDef HAL_SPI_Enable(SPI_HandleTypeDef *hSpi);
HAL_StatusTypeDef HAL_SPI_Disable(SPI_HandleTypeDef *hSpi);

HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hSpi, uint8_t *pData, uint32_t Size, uint32_t TimeOut);
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hSpi, uint8_t *pData, uint32_t Size, uint32_t TimeOut);
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hSpi, uint8_t *pTxData, uint8_t *pRxData, uint32_t Size, uint32_t TimeOut);

HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hSpi, uint8_t *pData, uint32_t Size);
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hSpi, uint8_t *pData, uint32_t Size);
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hSpi, uint8_t *pTxData, uint8_t *pRxData, uint32_t Size);
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT_IsComplete(SPI_HandleTypeDef *hSpi);
void              HAL_SPI_IRQHandler(SPI_HandleTypeDef *hSpi);


#ifdef __cplusplus
}
#endif

#endif /* __SYM32L010_HAL_SPI_H */


/************************ (C) COPYRIGHT SIYIMicro *****END OF FILE*************/
